/*******************************************************************************
 * Copyright (c) 2008 Sylvain Sicard.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser Public License v2.1
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * 
 * Contributors:
 *     Fabienne Boyer - initial API and implementation
 ******************************************************************************/
package fr.jade.reflex.control.lifecycle;

import org.objectweb.fractal.api.Component;
import org.objectweb.fractal.api.NoSuchInterfaceException;
import org.objectweb.fractal.api.control.IllegalLifeCycleException;
import org.objectweb.fractal.api.control.LifeCycleController;
import org.objectweb.fractal.api.factory.InstantiationException;

import fr.jade.fraclite.InitializationContext;
import fr.jade.fraclite.control.lifecycle.BasicLifeCycleController;
import fr.jade.reflex.api.control.LifeCycleNotificationController;
import fr.jade.reflex.api.control.ReflexController;
import fr.jade.reflex.util.Reflex;
import fr.jade.util.log.Logger;
import fr.jade.util.log.config.LogReflex;

/**
 * Provides an implementation of the
 * {@link org.objectweb.fractal.api.control.LifeCycleController} interface which
 * manages the causal connection with the dual level (i.e meta/execution): any
 * lifecycle operation performed on the current component is notified to the
 * lifecycle controller of dual component.
 * 
 * @author Fabienne Boyer 18/05/05
 * @author Sylvain Sicard
 * @contact Fabienne.Boyer@inrialpes.fr
 */

public class ReflexLifeCycleController extends BasicLifeCycleController implements LifeCycleNotificationController {


  /**
   * The <tt>weaveableRC</tt> field required by this mixin. This field is
   * supposed to reference the {@link ReflexController} interface of the
   * component to which this controller object belongs.
   */

  public ReflexController weaveableRC;

  public void initFcController (final InitializationContext ic) throws InstantiationException {
    Logger.println(LogReflex.debug, "ReflexContentController : init");
    weaveableRC = (ReflexController) ic.getInterface("reflex-controller");
    super.initFcController(ic);
  }
  
  protected LifeCycleNotificationController getDualCtrl() {
    assert weaveableRC != null : "Component must have a ReflexController";
    Component dual = weaveableRC.getCmpRef();
    assert dual != null : "Component must have a dual";
    LifeCycleNotificationController dualCtrl = null;
    try {
      dualCtrl = Reflex.getLifeCycleNotificationController(dual);
    } catch (NoSuchInterfaceException ignored) {}
    assert dualCtrl != null : "Dual component must have a LifeCycleNotificationController";
    return dualCtrl;
  }
  
  /**
   * Calls the overriden startFc method and then notifies the dual level of
   * the lifecycle operation.
   * 
   * @throws IllegalLifeCycleException
   *             if this component has a {@link LifeCycleController}
   *             interface, but it is not in an appropriate state to perform
   *             this operation.
   */
  public void startFc() throws IllegalLifeCycleException {
    startFcNotification();
    getDualCtrl().startFcNotification();
  }

  
  @Override
  public void rawStartFcNotification() throws IllegalLifeCycleException {
//    if(state.equals(STOPPED)){
//      if(innerImpl == null){
//        state=LifeCycleController.STARTED;
//      }else{
//        innerImpl.startFc();
//      }
//    }
    if(innerImpl == null){
      if(state.equals(STOPPED)){
        state=LifeCycleController.STARTED;
      }
    }else{
      innerImpl.startFc();
    }
  }

  @Override
  public void rawStopFcNotification() throws IllegalLifeCycleException {
//    if(state.equals(STARTED)){
//      if(innerImpl == null){
//        state=LifeCycleController.STOPPED;
//      }else{
//        innerImpl.stopFc();
//      }
//    }
    if(innerImpl == null){
      if(state.equals(STARTED)){
        state=LifeCycleController.STOPPED;
      }
    }else{
      innerImpl.stopFc();
    }
  }

  /**
   * Calls the overriden startFc method.
   * 
   * @throws IllegalLifeCycleException
   *             if this component has a {@link LifeCycleController}
   *             interface, but it is not in an appropriate state to perform
   *             this operation.
   */
  public void startFcNotification() throws IllegalLifeCycleException {
    Logger.println(LogReflex.debug, "startFcNotification ");
    super.startFc();
  }

  /**
   * Calls the overriden stopFc method and then notifies the dual level of the
   * lifecycle operation.
   * 
   * @throws IllegalLifeCycleException
   *             if this component has a {@link LifeCycleController}
   *             interface, but it is not in an appropriate state to perform
   *             this operation.
   */
  public void stopFc() throws IllegalLifeCycleException {
    stopFcNotification();
    getDualCtrl().stopFcNotification();
  }

  /**
   * Calls the overriden stopFc method.
   * 
   * @throws IllegalLifeCycleException
   *             if this component has a {@link LifeCycleController}
   *             interface, but it is not in an appropriate state to perform
   *             this operation.
   */
  public void stopFcNotification() throws IllegalLifeCycleException {
    Logger.println(LogReflex.debug, "stopFcNotification ");
    super.stopFc();
  }


}
